package org.kkk.sandbox.sandbox.impl;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

import cn.hutool.core.io.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.kkk.sandbox.dockerDemo;
import org.kkk.sandbox.enums.JudgeInfoMessageEnum;
import org.kkk.sandbox.enums.SandboxErrorEnum;
import org.kkk.sandbox.model.*;
import org.kkk.sandbox.sandbox.CodeSandbox;
import org.kkk.sandbox.utils.ProcessUtils;
@Slf4j
public class JavaNativeCodeSandbox implements CodeSandbox {
    public static final String FILE_STORAGE_DIR = "kkk_java";
    private static final String CLASS_NAME = "Main.java";
      protected File savaFile(ExecuteCodeRequest executeCodeRequest) {
        try {
            String rootPath = System.getProperty("user.dir");
            String rootDir = rootPath + File.separator + FILE_STORAGE_DIR;
            String codePath = rootDir + File.separator + UUID.randomUUID();
            String classPath = codePath + File.separator + CLASS_NAME;
            return FileUtil.writeString(executeCodeRequest.getCode(), classPath, StandardCharsets.UTF_8);
        }catch (Exception e)
        {
            throw new RuntimeException(SandboxErrorEnum.SAVE_ERROR.getMessage());
        }
    }

    protected ProcessExecuteMessage compileFile(File file) {
        try {
            Process  process = Runtime.getRuntime().exec("javac -encoding utf-8 " + file.getAbsolutePath());
            ProcessExecuteMessage processExecuteMessage = ProcessUtils.processExecute(process);
            if(ProcessUtils.isSuccess(processExecuteMessage.getExitCode()))
            {
                return processExecuteMessage;
            }

        } catch (IOException e) {
            //编译失败了
            throw new RuntimeException(SandboxErrorEnum.COMPILATION_ERROR.getMessage());
        }
        //否则编译错误
        throw new RuntimeException(SandboxErrorEnum.COMPILATION_ERROR.getMessage());
    }

    @Override
    public ExecuteCodeResponse executeCode(ExecuteCodeRequest executeCodeRequest) {
        try {
            File file = savaFile(executeCodeRequest);
            compileFile(file);
            ExecuteCodeResponse executeCodeResponse = run(executeCodeRequest, file);
            deleteFile(file);
            return executeCodeResponse;
        }catch (Exception e)
        {
            if(SandboxErrorEnum.COMPILATION_ERROR.getMessage().equals(e.getMessage()))
            {
                ArrayList<CaseExecuteInfo> caseExecuteInfos = new ArrayList<>();
                for (int i = 0; i < executeCodeRequest.getInputList().size(); i++) {
                    caseExecuteInfos.add(new CaseExecuteInfo(0L,0L,JudgeInfoMessageEnum.COMPILE_ERROR.getCode(),JudgeInfoMessageEnum.COMPILE_ERROR.getMessage()));
                }
                return new ExecuteCodeResponse(caseExecuteInfos);
            }
            else if(SandboxErrorEnum.SAVE_ERROR.getMessage().equals(e.getMessage()))
            {
                ArrayList<CaseExecuteInfo> caseExecuteInfos = new ArrayList<>();
                for (int i = 0; i < executeCodeRequest.getInputList().size(); i++) {
                    caseExecuteInfos.add(new CaseExecuteInfo(0L,0L,JudgeInfoMessageEnum.SYSTEM_ERROR.getCode(),JudgeInfoMessageEnum.SYSTEM_ERROR.getMessage()));
                }
                return new ExecuteCodeResponse(caseExecuteInfos);
            }
        }
        return null;
    }

    /**
     *
     * description: 执行方法
     * @param executeCodeRequest
     * @param file
     * @return ExecuteCodeResponse
     * @author  lenovo
     * create 2024/6/2-23:55
     */
    protected ExecuteCodeResponse run(ExecuteCodeRequest executeCodeRequest,File file) {
        ExecuteCodeResponse executeCodeResponse = new ExecuteCodeResponse();
        ArrayList<CaseExecuteInfo> caseExecuteInfos = new ArrayList<>();
        //执行代码
            for (String s : executeCodeRequest.getInputList()) {
                //遍历每一个实例
                String command = String.format("java -Dfile.encoding=UTF-8 -cp %s Main", file.getParentFile().getAbsolutePath());
                try {
                    Process codeExecProcess = Runtime.getRuntime().exec(command);
                    ProcessExecuteMessage processExecuteMessage = ProcessUtils.runInteractProcess(codeExecProcess, s, executeCodeRequest.getJudgeInfo());
                    CaseExecuteInfo caseExecuteInfo = new CaseExecuteInfo();
                    if (ProcessUtils.isSuccess(processExecuteMessage.getExitCode())) {
                        //成功
                        caseExecuteInfo.setMemory(processExecuteMessage.getExecMemory());
                        caseExecuteInfo.setTime(processExecuteMessage.getExecTime());
                        caseExecuteInfo.setOutput(processExecuteMessage.getMessage());
                        caseExecuteInfo.setState(JudgeInfoMessageEnum.WAITING.getCode());
                    } else {
                        caseExecuteInfo.setMemory(processExecuteMessage.getExecMemory());
                        caseExecuteInfo.setTime(processExecuteMessage.getExecTime());
                        caseExecuteInfo.setOutput(null);
                        caseExecuteInfo.setState(JudgeInfoMessageEnum.RUNTIME_ERROR.getCode());
                    }
                    caseExecuteInfos.add(caseExecuteInfo);
                } catch (Exception e) {
                    caseExecuteInfos.add(new CaseExecuteInfo(0L,0L,JudgeInfoMessageEnum.SYSTEM_ERROR.getCode(),JudgeInfoMessageEnum.SYSTEM_ERROR.getMessage()));
                }
            }
            executeCodeResponse.setCaseExecuteInfo(caseExecuteInfos);
        return executeCodeResponse;
    }
    protected void deleteFile(File file)
    {
        boolean del = FileUtil.del(file);
        if(!del)
        {
            log.error("删除失败，请尝试联系管理员手动删除");
        }
    }
}
